//my answer
//设置promise 状态
const PENDING = "pending"; //等待状态
const FULFILLED = 'fulfilled'; //成功状态
const REJECTED = 'rejected'; //失败状态

class MyPromise {
    constructor(executor) {

            try {
                //用于捕获错误信息 //并且立即调用函数
                executor(this.resolve, this.reject)
            } catch (error) {
                //调用reject传递错误信息
                this.reject(error)
            }
        }
        //初始化状态
    status = PENDING
        //初始化成功之后的值 用于保存结果
    success = undefined
        //初始化失败之后的值 用于保存结果
    error = undefined
        //用于保存成功回调，成功回调的默认值需要改成数组，因为只有数组可以存储多个回调函数
    successCallback = []
        //用于保存失败回调，失败回调的默认值需要改成数组，因为只有数组可以存储多个回调函数
    failCallback = []

    resolve = success => {
        //如果状态不是等待 则阻止程序执行
        if (this.status !== PENDING) return
            //把promise状态改为成功
        this.status = FULFILLED
            //保存成功之后的值
        this.success = success

        //这里使用while语句用successCallback.length作为循环条件，如果数组中有值，拿到数组中的第一个回调函数传值并执行
        while (this.successCallback.length) this.successCallback.shift()();
    }
    reject = error => {
        //如果状态不是等待 则阻止程序执行
        if (this.status !== PENDING) return
            //把promise状态改为失败
        this.status = REJECTED
            //保存失败之后的值
        this.error = error
            //这里使用while语句用failCallback.length作为循环条件，拿到数组中的第一个回调函数传值并执行
        while (this.failCallback.length) this.failCallback.shift()();

    }
    static all(array) {
        //准备一个空数组 用于接收值
        let result = []
            //定义一个值用于和result进行对比
        let index = 0;
        //返回一个promise
        return new MyPromise((resolve, reject) => {
            //定义一个函数，传递两个参数//
            function addDate(key, value) {
                //key作为数组result的下标为key，值为value
                result[key] = value;
                //每添加一个值 index就+1
                index++

                //逻辑判断如果index === 数组的长度，就意味着所有的同步的和异步都已经执行完了
                if (index === result.length) {
                    //调用resolve函数
                    resolve(result)
                }
            }
            //遍历数组中所有的值
            for (let i = 0; i < array.length; i++) {
                //接收数组中的值
                const element = array[i];
                //逻辑判断 是否为promise对象
                if (element instanceof MyPromise) {
                    //promise对象 成功就调用addDate函数，失败就调用reject函数
                    element.then(success => addDate(i, success), error => reject(error))
                } else {
                    //如果是普通值直接调用addDate函数
                    addDate(i, array[i])
                }
            }

        })
    }
    static race(array) {
            //返回一个promise对象
            return new MyPromise((resolve, reject) => {
                //遍历数组
                for (let i = 0; i < array.length; i++) {
                    //保存单个值 
                    const current = array[i];
                    //逻辑判断当前值是一个对象或者是当前值是一个function
                    if ((typeof current === 'object' && current !== null) || typeof current == 'function') {
                        //保存当前的then方法
                        let then = current.then;
                        if (typeof then == 'function') { // 比较哪个promise比较快，谁快用快
                            //改变this指向
                            then.call(current, resolve, reject)
                        } else {
                            //直接调用resolve方法
                            resolve(current);
                        }
                    } else {
                        //直接调用resolve方法
                        resolve(current);
                    }
                }
            });
        }
        //定义静态方法
    static resolve(value) {
            //逻辑判断如果是 promise对象就返回promise对象
            if (value instanceof MyPromise) value
                //如果不是promise对象 手动返回promise对象并且把value传递进去
            return new MyPromise((resolve, reject) => {
                resolve(value)
            })

        }
        //定义静态方法

    static reject(value) {
        //逻辑判断如果是 promise对象就返回promise对象
        if (value instanceof MyPromise) return value
            //如果不是promise对象 手动返回promise对象并且把value传递进去
        return new MyPromise((resolve, reject) => {
            reject(value)
        })
    }
    then(successCallback, failCallback) {

            //逻辑判断successCallback是否存在，如果不存在就传递一个函数进去
            successCallback = successCallback ? successCallback : success => success
                //逻辑判断successCallback是否存在，如果不存在就传递一个函数进去并且把错误信息抛出
            failCallback = failCallback ? failCallback : error => { throw error }
                //要实现then方法的链式调用必须创建一promise对象
                //新建一个promise对象
            let promise2 = new MyPromise((resolve, reject) => {
                    //逻辑判断如果当前状态为成功 则执行成功的回调并且把保存成功的值传递进去
                    if (this.status === FULFILLED) {

                        //此处仅仅将代码作为异步代码，延迟时间为0， 因为promise2 是在new MyPromise执行完成之后才能看到 在new MyPromise执行过程中是看不到的
                        //所以将代码变成异步代码
                        setTimeout(() => {
                            //捕获成功函数的错误信息
                            try {
                                //保存上一个函数的返回值
                                let x = successCallback(this.success)
                                    //并且把返回值传递给下一个then方法
                                    // resolve(x);

                                //判断X的值是普通值还是promise对象

                                //如果是普通值 直接调用resolve

                                //如果是promise对象 查看promise对象返回的结果

                                //再根据promise对象返回的结果 调用resolve还reject 

                                //所有同步代码执行完了才能看到promise2 
                                resolvePromise(promise2, x, resolve, reject)
                            } catch (error) {
                                //手动调用reject方法 把错误信息传递给下一个promise函数
                                reject(error)
                            }


                        }, 0);


                        //逻辑判断如果当前状态为成功 则执行失败的回调并且把失败的原因传递进去
                    } else if (this.status === REJECTED) {

                        setTimeout(() => {
                            //捕获错误函数的错误信息
                            try {
                                //保存上一个函数的返回值
                                let x = failCallback(this.error)
                                    //并且把返回值传递给下一个then方法
                                    // resolve(x);

                                //判断X的值是普通值还是promise对象

                                //如果是普通值 直接调用resolve

                                //如果是promise对象 查看promise对象返回的结果

                                //再根据promise对象返回的结果 调用resolve还reject 

                                //所有同步代码执行完了才能看到promise2 
                                resolvePromise(promise2, x, resolve, reject)
                            } catch (error) {
                                //手动调用reject方法 把错误信息传递给下一个promise函数
                                reject(error)
                            }


                        }, 0);
                    } else {
                        //当前状态为等待，也就是promise状态为pending，
                        //如果是等待的话那应该调用成功回调还是失败回调呢
                        //那当然是两个回调都无法调用，应为不知道到底是成功了还是还是失败了
                        //在这种情况下应该将成功回调和失败回调进行保存

                        //保存成功回调函数
                        //在这里有一个问题  this.successCallback一次只能存储一个函数这样的不符合要求
                        //所以在上面定义successCallback的时候将其定义为数组，这样就可以存储多个回调 ，将回调push进去

                        //重新编辑逻辑
                        this.successCallback.push(() => {
                            setTimeout(() => {
                                //捕获成功函数的错误信息
                                try {
                                    //保存上一个函数的返回值
                                    let x = successCallback(this.success)
                                        //并且把返回值传递给下一个then方法
                                        // resolve(x);

                                    //判断X的值是普通值还是promise对象

                                    //如果是普通值 直接调用resolve

                                    //如果是promise对象 查看promise对象返回的结果

                                    //再根据promise对象返回的结果 调用resolve还reject 

                                    //所有同步代码执行完了才能看到promise2 
                                    resolvePromise(promise2, x, resolve, reject)
                                } catch (error) {
                                    //手动调用reject方法 把错误信息传递给下一个promise函数
                                    reject(error)
                                }


                            }, 0);

                        });
                        //重新编辑逻辑
                        this.failCallback.push(() => {
                            setTimeout(() => {
                                //捕获错误函数的错误信息
                                try {
                                    //保存上一个函数的返回值
                                    let x = failCallback(this.error)
                                        //并且把返回值传递给下一个then方法
                                        // resolve(x);

                                    //判断X的值是普通值还是promise对象

                                    //如果是普通值 直接调用resolve

                                    //如果是promise对象 查看promise对象返回的结果

                                    //再根据promise对象返回的结果 调用resolve还reject 

                                    //所有同步代码执行完了才能看到promise2 
                                    resolvePromise(promise2, x, resolve, reject)
                                } catch (error) {
                                    //手动调用reject方法 把错误信息传递给下一个promise函数
                                    reject(error)
                                }


                            }, 0);
                        });
                    }
                })
                //返回promise对象
            return promise2
        }
        //捕捉方法
    catch (failCallback) {
        //处理失败的回调，第一个回调为undefined
        return this.then(undefined, error => failCallback(error))
    } finally(callback) {
        //通过this.then拿到当前promise对象的状态
        return this.then(
            success => {
                //返回一个promise对象，并且执行callback，最后把success返回
                return MyPromise.resolve(callback()).then(() => success)
            },
            error => {
                //返回一个promise对象，并且执行callback，最后把捕获的错误返回
                return MyPromise.resolve(callback()).then(() => { throw error })
            })
    }
}
//定义函数用于判断返回的是普通值还是promise对象
function resolvePromise(promise2, x, resolve, reject) {
    //逻辑判断是返回的是当前的promise对象 如果是抛出错误并且阻止程序执行
    if (promise2 === x) {

        return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))

    }
    //逻辑判断如果是promise对象
    if (x instanceof MyPromise) {
        //如果是成功的回调 就把值传递进去 失败的话就把失败的原因传递进去
        //  x.then(success => resolve(success), error => reject(error))
        //下面是简写写法
        x.then(resolve, reject)
    } else {
        //逻辑判断是普通值直接传递进去
        resolve(x)
    }

}
//遵循commjs规范 导出
module.exports = MyPromise;